#ifndef SIN_COMPUTE_H
#define SIN_COMPUTE_H
#include "kernel_tensor.h"
namespace AscendC {
const uint8_t SIN_HALF_CALC_PROCEDURE = 4;
const uint8_t SIN_FLOAT_NOREUSE_CALC_PROCEDURE = 3;
const uint8_t SIN_FLOAT_REUSE_CALC_PROCEDURE = 2;
constexpr float SIN_PI_FOR_X_TODIV = 0.3183098733425140380859375;
constexpr float SIN_PI = 3.1415926535897932384626433832795;
constexpr float SIN_RES_MULIT_SCA = 2.604926501e-6;
constexpr float SIN_RES_ADDICT_UP = -0.0001980894471;
constexpr float SIN_2ADDS = 0.008333049340;
constexpr float SIN_3ADDS = -0.1666665792;
constexpr float SIN_POINT_FIVE = 0.5;
constexpr float SIN_M4_SCA = 4.0;
constexpr float SIN_K2_SCA = -2.0;
__aicore__ inline void SinSignCompute(const LocalTensor<float>& dstTensor, const LocalTensor<float>& inputX,
    const LocalTensor<float>& roundTensor, const LocalTensor<float>& kpi, const uint32_t length)
{
    Mul(kpi, inputX, inputX, length);
    Muls(dstTensor, roundTensor, SIN_POINT_FIVE, length);
    Cast(dstTensor, dstTensor, RoundMode::CAST_FLOOR, length);
    Muls(dstTensor, dstTensor, SIN_M4_SCA, length);
    Muls(roundTensor, roundTensor, SIN_K2_SCA, length);
    Add(dstTensor, dstTensor, roundTensor, length);
    Adds(dstTensor, dstTensor, (float)1, length); 
}
__aicore__ inline void SinPolynomialApproximation(const LocalTensor<float>& dstTensor, const LocalTensor<float>& inputX,
    const LocalTensor<float>& roundTensor, const LocalTensor<float>& kpi, const uint32_t length)
{
    SinSignCompute(dstTensor, inputX, roundTensor, kpi, length);
    Muls(roundTensor, kpi, SIN_RES_MULIT_SCA, length);
    Adds(roundTensor, roundTensor, SIN_RES_ADDICT_UP, length);
    Mul(roundTensor, roundTensor, kpi, length);
    Adds(roundTensor, roundTensor, SIN_2ADDS, length);
    Mul(roundTensor, roundTensor, kpi, length);
    Adds(roundTensor, roundTensor, SIN_3ADDS, length);
    Mul(roundTensor, roundTensor, kpi, length);
    Adds(roundTensor, roundTensor, (float)1, length);
    Mul(roundTensor, roundTensor, inputX, length);
    Mul(dstTensor, roundTensor, dstTensor, length);
}
__aicore__ inline void SinRound(const LocalTensor<float>& inputX, const LocalTensor<float>& srcTensor,
                                const LocalTensor<float>& roundTensor, const LocalTensor<float>& kpi, const uint32_t length)
{
    Muls(roundTensor, srcTensor, SIN_PI_FOR_X_TODIV, length);
    Cast(roundTensor, roundTensor, RoundMode::CAST_ROUND, length);
    Muls(kpi, roundTensor, SIN_PI, length);
    Sub(inputX, srcTensor, kpi, length);
}
__aicore__ inline void SinCompute(const LocalTensor<float>& dstTensor, const LocalTensor<float>& srcTensor,
    const LocalTensor<float>& tmpTensor, const LocalTensor<float>& tmpTensor1, const uint32_t length)
{
    const BinaryRepeatParams binParams;
    LocalTensor<float> roundTensor = tmpTensor;
    LocalTensor<float> kpi = tmpTensor1;
    LocalTensor<float> inputX = srcTensor;
    SinRound(inputX, srcTensor, roundTensor, kpi, length);
    SinPolynomialApproximation(dstTensor, inputX, roundTensor, kpi, length);
}
} 
#endif